//TODO ? exit -1 ou continuer traitement avec affichage erreur ?

#include "book.h"
        
int readMe(char * user, char * buffer, int nbCharRead, int buffCursor)
{
        //TODO ajouter le test cursor > nbCharRead
        (void) nbCharRead;
        
        int i;
        char firstLine[7] = "Moi :\n\0";
        
        //lecture de la première ligne
        if(strncmp(firstLine, &(buffer[buffCursor]), 6) != 0)
        {
                printf("AdressBook error : expected line is \"Moi :\n\"\n");
                exit(-1);
        }
        
        buffCursor += 6;
        
        //lecture du nom d'utilisateur
        i=buffCursor;
        while(buffer[i] != ' ')
        {
                if(user[i-buffCursor] != buffer[i])
                {
                        printf("AdressBook error : the user name should be your's one\n");
                        exit(-1);
                }
                i++;
        }       
        buffCursor=i+1;
        
        //ajout du nom d'utilisateur
        strcpy(adressBook.me.name,user);
        
        //lecture de ": "
        if(buffer[buffCursor] != ':')
        {
                printf("AdressBook error : expected \"%s : \"\n", user);
                exit(-1);
        }
        buffCursor++;
        if(buffer[buffCursor] != ' ')
        {
                printf("AdressBook error : expected \"%s : \"\n", user);
                exit(-1);
        }
        buffCursor++;
        
        //lecture de l'adresse ip
        i=buffCursor;
        while(buffer[i] != '\n')
        {
                //TODO controler adresse ip
                adressBook.me.ip[i-buffCursor] = buffer[i];
                i++;
        }       
        buffCursor=i+1;
        
        //lecture de \n
        if(buffer[buffCursor] != '\n')
        {
                printf("AdressBook error : expected a new line after reading the block \"Moi\"\n");
                exit(-1);
        }
        buffCursor++;
        
        //pour faire joli
        adressBook.me.connected = 1;
        
        return buffCursor;
}

int readContacts(char * buffer, int nbCharRead, int buffCursor)
{
        //TODO ajouter le test cursor > nbCharRead
        (void) nbCharRead;(void) nbCharRead;
        
        int i,j, nbContacts=0;
        char firstLine[12] = "Contacts : \0";
        char c;
        char * tmp = &c;
        
        //lecture de la première ligne
        if(strncmp(firstLine, &(buffer[buffCursor]), 11) != 0)
        {
                printf("AdressBook error : expected line is \"Contacts : <nbContacts>\"\n");
                exit(-1);
        }
        
        buffCursor +=11;
        
        //lecture du nombre de contacts
        i=buffCursor;
        while(buffer[i] != '\n')
        {
                //TODO controler buffer[i] appartient à [0-9]
                c=buffer[i];
                nbContacts = nbContacts * 10 + atoi(tmp);
                i++;
        }       
        buffCursor=i+1;
        
        //allocation du nombre de contacts
        adressBook.nbContacts = nbContacts;
        adressBook.contacts = malloc (nbContacts * sizeof(Contact));
        
        //lecture de chaque contact
        for(j=0; j<nbContacts; j++)
        {
                //lecture du nom d'utilisateur
                i=buffCursor;
                while(buffer[i] != ' ')
                {
                        adressBook.contacts[j].name[i-buffCursor] = buffer[i];
                        i++;
                }       
                buffCursor=i+1;
                        
                //lecture de ": "
                if(buffer[buffCursor] != ':')
                {
                        printf("AdressBook error : expected \"%s : \"\n", adressBook.contacts[j].name);
                        exit(-1);
                }
                buffCursor++;
                if(buffer[buffCursor] != ' ')
                {
                        printf("AdressBook error : expected \"%s : \"\n", adressBook.contacts[j].name);
                        exit(-1);
                }
                buffCursor++;
        
                //lecture de l'adresse ip
                i=buffCursor;
                while(buffer[i] != '\n')
                {
                        //TODO controler adresse ip
                        adressBook.contacts[j].ip[i-buffCursor] = buffer[i];
                        i++;
                }       
                buffCursor=i+1;
                
                //par défaut, un contact n'est pas connecté
                adressBook.contacts[j].connected = 0;
        }
        
        //lecture de \n
        if(buffer[buffCursor] != '\n')
        {
                printf("AdressBook error : expected a new line after reading the block \"Contacts\"\n");
                exit(-1);
        }
        buffCursor++;
        
        return buffCursor;      
}

int readGroups(char * buffer, int nbCharRead, int buffCursor)
{
        //TODO ajouter le test cursor > nbCharRead
        (void) nbCharRead;
        
        int i,j, k, nbGroups=0, nbMembers;
        char firstLine[11] = "Groupes : \0";
        char c;
        char * tmp = &c;
        
        //lecture de la première ligne
        if(strncmp(firstLine, &(buffer[buffCursor]), 10) != 0)
        {
                printf("AdressBook error : expected line is \"Groupes : <nbGroups>\"\n");
                exit(-1);
        }
                
        buffCursor +=10;
        
        //lecture du nombre de groupes
        i=buffCursor;
        while(buffer[i] != '\n')
        {
                //TODO controler buffer[i] appartient à [0-9]
                c=buffer[i];
                nbGroups = nbGroups * 10 + atoi(tmp);
                i++;
        }       
        buffCursor=i+1;
        
        //allocation du nombre de groupes
        adressBook.nbGroups = nbGroups;
        adressBook.groups = malloc (nbGroups * sizeof(Group));
        
        //lecture de chaque contact
        for(j=0; j<nbGroups; j++)
        {
                //lecture du nom du groupe
                i=buffCursor;
                while(buffer[i] != ' ')
                {
                        adressBook.groups[j].groupName[i-buffCursor] = buffer[i];
                        i++;
                }       
                buffCursor=i+1;
        
                //lecture de ": "
                if(buffer[buffCursor] != ':')
                {
                        printf("AdressBook error : expected \"%s : \"\n", adressBook.contacts[j].name);
                        exit(-1);
                }
                buffCursor++;
                if(buffer[buffCursor] != ' ')
                {
                        printf("AdressBook error : expected \"%s : \"\n", adressBook.contacts[j].name);
                        exit(-1);
                }
                buffCursor++;
                
                //lecture du nombre de membres
                nbMembers = 0;
                
                i=buffCursor;
                while(buffer[i] != ' ')
                {
                        //TODO controler buffer[i] appartient à [0-9]
                        c=buffer[i];
                        nbMembers = nbMembers * 10 + atoi(tmp);
                        i++;
                }       
                buffCursor=i+1;
                                
                
                //allocation des membres
                adressBook.groups[j].nbMembers = nbMembers;
                adressBook.groups[j].members = malloc(nbMembers * sizeof(char *));
                
                //TODO controller ' ' au centre, '\n' dernier, '\0' tout dernier
                for(k=0; k<nbMembers ; k++)
                {               
                        adressBook.groups[j].members[k] = malloc(SIZENAME * sizeof(char));
                        
                        i=buffCursor;                   
                        while(buffer[i] != ' ' && buffer[i] != '\n' && buffer[i] != '\0')
                        {
                                adressBook.groups[j].members[k][i-buffCursor] = buffer[i];
                                i++;
                        }       
                        buffCursor=i+1;
                }
        
        }
        
        return buffCursor;
}
                
void openBook(char * user)
{
        int i, nameSize, fd, buffCursor, nbCharRead;
        char * fileName;
        char buffer[BUFFERSIZE];
        
        nameSize = strlen(user); //nombre de lettres dans le nom de l'utilisateur
        fileName = malloc ((11 + nameSize) * sizeof(char)); //11 : panda_<name>.txt\0
        
        //création du nom de fichier à partir du nom d'utilisateur
        fileName[0] = 'p';
        fileName[1] = 'a';
        fileName[2] = 'n';
        fileName[3] = 'd';
        fileName[4] = 'a';
        fileName[5] = '_';
        for(i=6; i< 6+nameSize; i++)
        {
                fileName[i] = user[i-6];
        }
        fileName[i++] = '.';
        fileName[i++] = 't';
        fileName[i++] = 'x';
        fileName[i++] = 't';
        fileName[i] = '\0';
        
        //ouverture du fichier
        fd = open (fileName, O_RDONLY);
        if(fd <0)
        {
                printf("AdressBook error : could not find %s\n",fileName);
                exit(-1);
        }
        
        //première lecture du fichier
        buffCursor = 0; //curseur sur le buffer
        nbCharRead = read(fd, buffer, BUFFERSIZE);
        
        //lecture des infos sur le contact
        if((buffCursor=readMe(user, buffer, nbCharRead, buffCursor)) < 0)
        {
                //TODO si pb buffcursor > nbCharREad
        } 
        
        //lecture des infos sur les contacts
        if((buffCursor=readContacts(buffer, nbCharRead, buffCursor)) < 0)
        {
                //TODO si pb buffcursor > nbCharREad
        } 
        
        //lecture des infos sur les groupes
        if((buffCursor=readGroups(buffer, nbCharRead, buffCursor)) < 0)
        {
                //TODO si pb buffcursor > nbCharREad
        } 
        
        close(fd);
}

char * uitoa(int x)
{// 134 -> {'4','3','1'} -> {'1','3','4'}
        int i=0, temp = x;
        char * result;
        
        while(x>0)
        {
        		x/=10;
        		i++;
        	}
        	
        	result = malloc((i+1)*sizeof(char));
        	
        	sprintf(result,"%d",temp);
        	
        	return result;
}

void saveBook()
{
        char firstLineMe[7] = "Moi :\n";
        char firstLineContacts[14] = "\n\nContacts : ";
        char firstLineGroups[12] = "\nGroupes : ";
        char newLine[2] = "\n";
        char newSpace[2] = " ";
        char newCombo[4] = " : ";
        char * buffer;
        char * temp;
        int buffSize=0;
        int tempSize;
        int size, sizeBis;
        int i,j;
        int nameSize, fd;
        char * fileName;
        nameSize = strlen(adressBook.me.name); //nombre de lettres dans le nom de l'utilisateur
        //fileName = malloc (12 * nameSize * sizeof(char)); //11 : panda_<name>.txt\0
        fileName = malloc ((11 + nameSize) * sizeof(char)); //11 : panda_<name>.txt\0
        
        //création du nom de fichier à partir du nom d'utilisateur
        fileName[0] = 'p';
        fileName[1] = 'a';
        fileName[2] = 'n';
        fileName[3] = 'd';
        fileName[4] = 'a';
        fileName[5] = '_';
        for(i=6; i< 6+nameSize; i++)
        {
                fileName[i] = adressBook.me.name[i-6];
        }
        //fileName[i++] = 'a';
        fileName[i++] = '.';
        fileName[i++] = 't';
        fileName[i++] = 'x';
        fileName[i++] = 't';
        fileName[i] = '\0';
        
        //ouverture du fichier
        fd = open (fileName, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
        if(fd <0)
        {
                printf("AdressBook error : could not find %s\n",fileName);
                exit(-1);
        }
                
        //bloc Moi
        tempSize=6;
        buffer = malloc((buffSize+tempSize)*sizeof(char));
        strncpy(&(buffer[buffSize]),firstLineMe,tempSize);
        buffSize+=tempSize;
        
        tempSize = strlen(adressBook.me.name);
        buffer = realloc(buffer,(buffSize+tempSize)*sizeof(char));
        strncpy(&(buffer[buffSize]),adressBook.me.name,tempSize);
        buffSize+=tempSize;
        
        tempSize = 3;
        buffer = realloc(buffer,(buffSize+tempSize)*sizeof(char));
        strncpy(&(buffer[buffSize]),newCombo,tempSize);
        buffSize+=tempSize;
        
        tempSize = strlen(adressBook.me.ip);
        buffer = realloc(buffer,(buffSize+tempSize)*sizeof(char));
        strncpy(&(buffer[buffSize]),adressBook.me.ip,tempSize);
        buffSize+=tempSize;
        
        //bloc Contacts
        tempSize=13;
        buffer = realloc(buffer,(buffSize+tempSize)*sizeof(char));
        strncpy(&(buffer[buffSize]),firstLineContacts,tempSize);
        buffSize+=tempSize;
        
        size = adressBook.nbContacts;
        temp = uitoa(size);
        tempSize = strlen(temp);
        buffer = realloc(buffer,(buffSize+tempSize)*sizeof(char));
        strncpy(&(buffer[buffSize]),temp,tempSize);
        buffSize+=tempSize;
        free(temp);
        
        tempSize = 1;
        buffer = realloc(buffer,(buffSize+tempSize)*sizeof(char));
        strncpy(&(buffer[buffSize]),newLine,tempSize);
        buffSize+=tempSize;
        
        for(i=0; i<size; i++)
        {
                tempSize = strlen(adressBook.contacts[i].name);
                buffer = realloc(buffer,(buffSize+tempSize)*sizeof(char));
                strncpy(&(buffer[buffSize]),adressBook.contacts[i].name,tempSize);
                buffSize+=tempSize;
        
                tempSize = 3;
                buffer = realloc(buffer,(buffSize+tempSize)*sizeof(char));
                strncpy(&(buffer[buffSize]),newCombo,tempSize);
                buffSize+=tempSize;
        
                tempSize = strlen(adressBook.contacts[i].ip);
                buffer = realloc(buffer,(buffSize+tempSize)*sizeof(char));
                strncpy(&(buffer[buffSize]),adressBook.contacts[i].ip,tempSize);
                buffSize+=tempSize;
                
                tempSize = 1;
                buffer = realloc(buffer,(buffSize+tempSize)*sizeof(char));
                strncpy(&(buffer[buffSize]),newLine,tempSize);
                buffSize+=tempSize;
        }
        
        //bloc groupes
        tempSize=11;
        buffer = realloc(buffer,(buffSize+tempSize)*sizeof(char));
        strncpy(&(buffer[buffSize]),firstLineGroups,tempSize);
        buffSize+=tempSize;
        
        size = adressBook.nbGroups;
        temp = uitoa(size);
        tempSize = strlen(temp);
        buffer = realloc(buffer,(buffSize+tempSize)*sizeof(char));
        strncpy(&(buffer[buffSize]),temp,tempSize);
        buffSize+=tempSize;
        free(temp);
        
        tempSize = 1;
        buffer = realloc(buffer,(buffSize+tempSize)*sizeof(char));
        strncpy(&(buffer[buffSize]),newLine,tempSize);
        buffSize+=tempSize;
        
        for(i=0; i<size; i++)
        {
                tempSize = strlen(adressBook.groups[i].groupName);
                buffer = realloc(buffer,(buffSize+tempSize)*sizeof(char));
                strncpy(&(buffer[buffSize]),adressBook.groups[i].groupName,tempSize);
                buffSize+=tempSize;
        
                tempSize = 3;
                buffer = realloc(buffer,(buffSize+tempSize)*sizeof(char));
                strncpy(&(buffer[buffSize]),newCombo,tempSize);
                buffSize+=tempSize;
                
                sizeBis = adressBook.groups[i].nbMembers;
                temp = uitoa(sizeBis);
                tempSize = strlen(temp);
                buffer = realloc(buffer,(buffSize+tempSize)*sizeof(char));
                strncpy(&(buffer[buffSize]),temp,tempSize);
                buffSize+=tempSize;
                free(temp);
                
                tempSize = 1;
                buffer = realloc(buffer,(buffSize+tempSize)*sizeof(char));
                strncpy(&(buffer[buffSize]),newSpace,tempSize);
                buffSize+=tempSize;
                
                for(j=0; j<sizeBis-1; j++)
                {
                        tempSize = strlen(adressBook.groups[i].members[j]);
                        buffer = realloc(buffer,(buffSize+tempSize)*sizeof(char));
                        strncpy(&(buffer[buffSize]),adressBook.groups[i].members[j],tempSize);
                        buffSize+=tempSize;
                        
                        tempSize = 1;
                        buffer = realloc(buffer,(buffSize+tempSize)*sizeof(char));
                        strncpy(&(buffer[buffSize]),newSpace,tempSize);
                        buffSize+=tempSize;
                }
                
                tempSize = strlen(adressBook.groups[i].members[j]);
                buffer = realloc(buffer,(buffSize+tempSize)*sizeof(char));
                strncpy(&(buffer[buffSize]),adressBook.groups[i].members[j],tempSize);
                buffSize+=tempSize;
                
                tempSize = 1;
                buffer = realloc(buffer,(buffSize+tempSize)*sizeof(char));
                strncpy(&(buffer[buffSize]),newLine,tempSize);
                buffSize+=tempSize;
        }
        
        buffer = realloc(buffer,(buffSize)*sizeof(char));
        buffer[buffSize]= '\0';
        
        write(fd, buffer, buffSize);
        
        close(fd);
}

void freeBook()
{
        int i,j;
        
        memset(adressBook.me.name, '\0', SIZENAME);
        memset(adressBook.me.ip, '\0', SIZENAME);
        adressBook.me.connected = 0;
        
        for(i=0; i<adressBook.nbContacts; i++)
        {
                memset(adressBook.contacts[i].name, '\0', SIZENAME);
                memset(adressBook.contacts[i].ip, '\0', SIZENAME);
                adressBook.contacts[i].connected = 0;
        }
        free(adressBook.contacts);
        adressBook.nbContacts = 0;
        
        for(i=0; i<adressBook.nbGroups; i++)
        {
                for(j=0; j<adressBook.groups[i].nbMembers; j++)
                {
                        free(adressBook.groups[i].members[j]);
                }
                adressBook.groups[i].nbMembers = 0;
                free(adressBook.groups[i].members);
        }
        free(adressBook.groups);
        adressBook.nbGroups = 0;
}

void printBook()
{
        int i,j;
        printf("Moi :\n");
        printf("%s : %s\n", adressBook.me.name, adressBook.me.ip);
        printf("\n");
        
        printf("Contacts : %d\n",adressBook.nbContacts);
        for(i=0;i<adressBook.nbContacts;i++)
        {
                printf("%s : %s\n", adressBook.contacts[i].name, adressBook.contacts[i].ip);
        }
        printf("\n");
        
        printf("Groupes : %d\n",adressBook.nbGroups);
        for(i=0;i<adressBook.nbGroups;i++)
        {
                printf("%s : %d", adressBook.groups[i].groupName, adressBook.groups[i].nbMembers);
                for(j=0;j<adressBook.groups[i].nbMembers;j++)
                {
                        printf(" %s", adressBook.groups[0].members[j]);
                }
                printf("\n");
        }
        printf("\n");   
}

void addContact(char * name, char * ip)
{
        if(strlen(name)>SIZENAME)
        {
                printf("Add Contact error : name %s is too long\n", name);
                exit(-1);
        }
        
        if(strlen(ip)>SIZEIP)
        {
                printf("Add Contact error : ip %s is too long\n", ip);
                exit(-1);
        }
        
        if(searchContactIndex(name) == -1)
        {
                adressBook.nbContacts++;
        
                adressBook.contacts = realloc(adressBook.contacts, adressBook.nbContacts * sizeof(Contact));
        
                strcpy(adressBook.contacts[adressBook.nbContacts-1].name,name);
                strcpy(adressBook.contacts[adressBook.nbContacts-1].ip,ip);
                adressBook.contacts[adressBook.nbContacts-1].connected = 1;
        
                saveBook();
        }
        else
        {
                printf("Add Contact error : contact %s already exist\n",name);
                exit(-1);
        }       
}

int searchContactIndex(char * name)
{
        int find=0, i=0; //TODO find -> bool
        
        while(!find && i<adressBook.nbContacts)
        {
                if(strcmp(adressBook.contacts[i].name, name) != 0)
                {
                        i++;
                }
                else
                {
                        find = 1;
                }
        }
        
        if(find)
        {
                return i;
        }
        else
        {
                return -1;
        }       
}

//TODO int -> bool
//1 -> co / 0 -> deco
int coDecoContact(char * name, int state)
{
        int i;
        i=searchContactIndex(name);
        
        if(i!=-1)
        {
                if(state)
                {
                        adressBook.contacts[i].connected = 1;
                }
                else
                {
                        adressBook.contacts[i].connected = 0;
                }
        }
        
        return i;
}

void connectionContact(char * name)
{       
        if(strlen(name)>SIZENAME)
        {
                printf("Connection Contact error : name %s is too long\n", name);
                exit(-1);
        }
        
        if(coDecoContact(name, 1)==-1)//TODO bool_t
        {
                printf("Connection Contact error : contact %s not found\n", name);
                exit(-1);
        }
}

void deconnectionContact(char * name)
{
        if(strlen(name)>SIZENAME)
        {
                printf("Deconnection Contact error : name %s is too long\n", name);
                exit(-1);
        }
        
        if(coDecoContact(name, 0)==-1)//TODO bool_t
        {
                printf("Deconnection Contact error : contact %s not found\n", name);
                exit(-1);
        }
}

